var express = require('express');
var jsSHA = require('jssha');
var utils = require('utility');
var config = require('config');
var fs = require('fs');
var path = require('path');

var xml2js = require('xml2js');
var xmlBuilder = new xml2js.Builder({cdata: true, rootName: 'xml'});
var thunkify = require('thunkify');
var co_xml2json = thunkify(xml2js.parseString);

var _ = require('lodash');
var co = require('co');
var request = require('request');
var coRequest = require('co-request');
var moment = require('moment');
var iconv = require('iconv-lite');

var dao = require('../dao');
var LicenseCenter = require('../lib/LicenseCenter');
var idGen = require('../lib/idGen');
var commonUtils = require('../lib/commonUtils');
var constant = require('../constant');

var router = express.Router();

var
    appId = config.appId,
    mchId = config.mchId,
    secret = config.secret,
    paykey = config.payKey,

    flowServerUrl = config.flowServer_url,
    flowServerApiKey = config.flowServer_apiKey,
    flowServerAccount = config.flowServer_account,

    certFile = path.resolve(process.cwd(), 'ssl/apiclient_cert.pem'),
    keyFile = path.resolve(process.cwd(), 'ssl/apiclient_key.pem'),
    caFile = path.resolve(process.cwd(), 'ssl/rootca.pem');

router.get('/', function(req, res){
    res.redirect('admin');
});
/**
 * 获取授权后,然后跳转到卡号绑定页面
 */
router.get('/wechat/auth', function (req, res) {
    var view = req.query.view;
    // var authUrl;
    // switch (view){
    //     case 'bind':{
    //         authUrl= 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx7245a4f60dfe7d1d&redirect_uri=http://service.lvyou189.cn/wechat/view/bind&response_type=code&scope=snsapi_base&state=state#wechat_redirect';
    //         break;
    //     }
    //     case 'charge':{
    //         authUrl= 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx7245a4f60dfe7d1d&redirect_uri=http://service.lvyou189.cn/wechat/charge&response_type=code&scope=snsapi_base&state=state#wechat_redirect';
    //         break;
    //     }
    //     case 'mobile_flow_charge':{
    //         authUrl= 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx7245a4f60dfe7d1d&redirect_uri=http://service.lvyou189.cn/wechat/mobile_flow_charge&response_type=code&scope=snsapi_base&state=state#wechat_redirect';
    //         break;
    //     }
    // }
    var authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=http://service.lvyou189.cn/wechat/view/${view}&response_type=code&scope=snsapi_base&state=state#wechat_redirect`;
    res.redirect(authUrl);
});

/**
 * 已获取授权,维护session,渲染卡号绑定页面
 */
router.get('/wechat/view/bind', function (req, res) {
    var code = req.query.code;
    var state = req.query.state;
    console.log('code = ' + code);
    console.log('state = ' + state);
    var tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${secret}&code=${code}&grant_type=authorization_code`;
    co(function*() {
        var response = yield coRequest(tokenUrl);
        if (response.statusCode === 200 && !response.body.errcode) {
            req.session.user = JSON.parse(response.body);
            console.log(response.body);
            res.render('wechat/bind', {title: '旅游WIFI', openId: response.body.openid});
        }
    });
});

router.get('/wechat/view/charge', function (req, res) {
    var code = req.query.code;
    var state = req.query.state;

    var tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${secret}&code=${code}&grant_type=authorization_code`;
    co(function*() {
        var response = yield coRequest(tokenUrl);
        if (response.statusCode === 200 && !response.body.errcode) {
            var tokenResp = JSON.parse(response.body);
            var user = yield dao.User.findOne({open_id : tokenResp.openid});
            console.log(user);
            req.session.user = user;

            var jsapi_ticket = yield LicenseCenter.jsapi_ticket();
            var configSignBody = {
                noncestr: String(Math.random() * 10000000000000000),
                jsapi_ticket: jsapi_ticket,
                timestamp: (new Date().getTime() / 1000).toFixed(0),
                url: 'http://service.lvyou189.cn/wechat/charge'
            };
            var configSign = getConfigSign(configSignBody);

            configSignBody.appId = appId;
            configSignBody.sign = configSign;

            res.render('wechat/charge', {title: '旅游WIFI', openId: response.body.openid, config : configSignBody});
        }
    });
});

router.get('/wechat/view/mobile_flow_charge', function (req, res) {
    var code = req.query.code;
    var state = req.query.state;

    console.log('mobile_flow_charge visiting');

    var tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${appId}&secret=${secret}&code=${code}&grant_type=authorization_code`;
    co(function*() {
        var response = yield coRequest(tokenUrl);
        if (response.statusCode === 200 && !response.body.errcode) {
            var tokenResp = JSON.parse(response.body);
            var user = yield dao.User.findOne({open_id : tokenResp.openid});
            console.log(user);
            req.session.user = user;

            var jsapi_ticket = yield LicenseCenter.jsapi_ticket();
            var configSignBody = {
                noncestr: String(Math.random() * 10000000000000000),
                jsapi_ticket: jsapi_ticket,
                timestamp: (new Date().getTime() / 1000).toFixed(0),
                url: 'http://service.lvyou189.cn/wechat/view/mobile_flow_charge'
            };
            var configSign = getConfigSign(configSignBody);

            configSignBody.appId = appId;
            configSignBody.sign = configSign;

            var renderData = {
                title: '通用流量',
                openId: tokenResp.openid,
                config : configSignBody,
                defaultPackage : [
                    {
                        package : '10',
                        name : '10M',
                        price : 3.00
                    },
                    {
                        package : '30',
                        name : '30M',
                        price : 5.00
                    },
                    {
                        package : '70',
                        name : '70M',
                        price : 10.00
                    },
                    {
                        package : '150',
                        name : '150M',
                        price : 20.00
                    },
                    {
                        package : '500',
                        name : '500M',
                        price : 30.00
                    },
                    {
                        package : '1000',
                        name : '1G',
                        price : 50.00
                    },
                    {
                        package : '2000',
                        name : '2G',
                        price : 70.00
                    }
                ]
            };

            res.render('wechat/mobile_flow_charge', renderData);
        }
    });
});

/**
 * 执行流量卡绑定操作, 检测卡号合法性, 存储绑定关系到mongodb:users
 */
router.post('/bind', function (req, res) {
    var user = req.session.user;
    var card = req.body.card;
    var pwd = req.body.pwd;
    var mobile = req.body.mobile;

    co(function*(){
        var cardInfo = yield dao.Card.findOne({card_id : card});
        if(!cardInfo){
            return res.status(500).json('卡号不存在');
        }
        if(cardInfo.card_pwd !== pwd){
            return res.status(500).json('卡号密码错误');
        }

        user.card = card;
        user.mobile = mobile;

        var conditon = {open_id: user.openid};
        var update = {
            card_id: card,
            mobile: mobile
        };
        dao.User.update(conditon, update, function(err){
            if(err){
                res.status(500).json(err);
            }else{
                res.status(200).json('ok');
            }
        });
    });
});

var chargeFee = {
    '1G' : 2000,
    '2G' : 4000
};

router.post('/charge', function(req, res){
    var user = req.session.user;
    var chargePackage = req.body.chargePackage;
    var clientIP = req.ip.split(':')[3];
    console.log(`充值客户端IP:${clientIP}, 充值流量:${chargePackage}`);

    if(!chargeFee[chargePackage]){
        return res.status(500).json('充值套餐不存在:' + chargePackage);
    }

    co(function*(){
        var card = yield dao.Card.findOne({card_id : user.card_id});
        if(!card){
            return res.status(500).json('绑定卡号不存在:' + user.card_id);
        }

        var order = {
            order_id : idGen.orderId(user.open_id),
            mobile : card.mobile,
            amount : chargeFee[chargePackage],
            package : chargePackage,
            payer_id : user._id,
            status : constant.OrderStatus.PAY_NO,
            type : constant.OrderType.CARD,
            create_time : new Date()
        };

        var orderInstance = new dao.Order(order);
        var effactRows = yield orderInstance.save();
        console.log(effactRows);

        var postData = {
            appid : appId,
            mch_id : mchId,
            device_info : 'WEB',
            nonce_str : String(Math.random() * 10000000000000000),
            body : `${chargePackage} 流量套餐`,
            out_trade_no : order.order_id,          //'内部订单号',
            total_fee : chargeFee[chargePackage],
            spbill_create_ip : clientIP,
            notify_url : 'http://service.lvyou189.cn/charge/callback',
            trade_type : 'JSAPI',
            openid : user.open_id
        };
        postData.sign = getSign(postData, paykey);
        var postXML = xmlBuilder.buildObject(postData);

        console.log('prepay request 2 wechat ------->');
        var response = yield coRequest.post({
            url : 'https://api.mch.weixin.qq.com/pay/unifiedorder',
            body : postXML
        });
        console.log('prepay req fin');
        //request error
        if (response.statusCode !== 200) {
            yield orderInstance.update({status : constant.OrderStatus.ORDER_FAIL});
            return res.status(500).json('微信支付服务错误');
        }

        console.log(response.body);
        var result = yield co_xml2json(response.body, {explicitArray: false});
        //签名错误等数据错误
        if(result.xml.return_code === 'FAIL') {
            yield orderInstance.update({status : constant.OrderStatus.ORDER_FAIL});
            return res.status(500).json(result.xml.return_msg);
        }
        //业务错误
        if(result.xml.result_code === 'FAIL'){
            yield orderInstance.update({status : constant.OrderStatus.ORDER_FAIL});
            return res.status(500).json(result.xml.err_code_des);
        }

        var prepay_id = result.xml.prepay_id;


        var paySignBody = {
            appId : appId,
            timeStamp : (new Date().getTime() / 1000).toFixed(0),
            nonceStr : String(Math.random() * 10000000000000000),
            'package' : `prepay_id=${prepay_id}`,
            signType : 'MD5'
        };

        var paySign = getSign(paySignBody, paykey);

        var finalResult = {
            appId : appId,
            nonceStr : paySignBody.nonceStr,
            timestamp: paySignBody.timeStamp,
            prepayId : prepay_id,
            'package' : paySignBody.package,
            signType : paySignBody.signType,
            paySign : paySign
        };

        console.log(finalResult);
        res.json(finalResult);

    }).catch(function(err){
        console.log(err);
        res.status(500).json(err);
    });
});

/**
 * 支付完成的回调接口
 */
router.post('/charge/callback', function(req, res){
    var post_data = "";
    req.on("data", function (data) {
        post_data = data;
    });
    req.on("end", function () {
        console.log('pay callback');
        co(function * (){
            var xmlStr = post_data.toString('utf-8', 0, post_data.length);

            var payResult = yield co_xml2json(xmlStr, {explicitArray: false});
            payResult = payResult.xml;

            if(payResult.return_code === 'FAIL'){
                console.log('pay callback msg:' + payResult.return_msg);
                return;
            }
            //签名校验
            var backSign = payResult.sign;
            delete payResult.sign;
            var trueSign = getSign(payResult, paykey);
            if(backSign !== trueSign){
                throw 'LIAR:签名验证失败';
            }

            var orderId = payResult.out_trade_no;
            var order = yield dao.Order.findOne({order_id : orderId});
            console.log(orderId + ' : ' + order);
            var updateData = {
                pay_log : payResult,
                update_time : new Date()
            };

            if(payResult.result_code === 'SUCCESS'){
                updateData.status = constant.OrderStatus.PAY_FIN;
                if(order.type === constant.OrderType.MOBILE){
                    chargeFlowForMobile(order);
                }
            }else{
                updateData.status = constant.OrderStatus.PAY_FAIL;
                console.log(`${payResult.err_code} : ${payResult.err_code_des}`);
            }
            yield order.update(updateData);

            var respMsg = {
                return_code : 'SUCCESS',
                return_msg : 'OK'
            };
            var respXML = xmlBuilder.buildObject(respMsg);
            res.send(respXML);
        }).catch(function(err){
            console.log(err);
            var respMsg = {
                return_code : 'FAIL',
                return_msg : err
            };
            var respXML = xmlBuilder.buildObject(respMsg);
            res.send(respXML);
        });
    });

});

/**
 * 手机流量充值完成的回调接口, 更新订单状态, 给用户发送到账提醒
 */
router.post('/flow/charge/callback', function(req, res){
    var reports = req.body;
    co(function*(){
        for(var i in reports){
            var report = reports[i];

            var condition = {
                order_id : report.OutTradeNo,
                outer_task_id : report.TaskID,
                status : constant.OrderStatus.PAY_FIN
            };
            var updateData = {
                status : constant.OrderStatus.ORDER_FIN,
                outer_task_report : report
            };
            var er = yield dao.Order.update(condition, updateData);
            console.log(`充值状态更新${er.nModified}条, taskId : ${report.TaskID}, status : ${report.Status}, result : ${report.ReportCode}, orderId : ${report.OutTradeNo}`);

            var order = yield dao.Order.findOne({order_id : report.OutTradeNo});
            if(!order){
                continue;
            }
            chargeReportHandler(order);
        }
    }).catch(function(err){
        console.log(err);
    });
    res.send('ok');
});

function packageParser(packageName){
    if(packageName.indexOf('M') != -1){
        return +(packageName.slice(0, packageName.indexOf('M')));
    }
    if(packageName.indexOf('G') != -1){
        return +(packageName.slice(0, packageName.indexOf('G'))) * 1000;
    }
}

function chargeFlowForMobile(order){
    co(function * (){
        var chargePackage = packageParser(order.package);

        var body = {
            account : flowServerAccount,
            mobile : order.mobile,
            'package' : chargePackage
        };

        body.sign = getSign(body, flowServerApiKey);
        body.action = 'charge';
        body.v = '1.1';
        body.range = '0';
        body.outtradeno = order.order_id;

        var url = commonUtils.buildUrl(flowServerUrl, body);
        console.log(url);

        var result = yield coRequest.get(url);
        if(result.statusCode !== 200){
            throw '网络异常';
        }
        var resultBody = JSON.parse(result.body);
        console.log(resultBody);

        if(resultBody.Code == 0){
            var updateData = {
                outer_task_id : resultBody.TaskID,
                update_time: new Date()
            };

            yield order.update(updateData);
        }else{
            throw resultBody.Message;
        }
    }).catch(function(err){
        console.error(err);
        console.error(err.stack);
    });
}

function getConfigSign(body){
    var keyArr = _.keys(body).sort();
    var tmp = [];
    _.each(keyArr, function(key){
        if(body[key]){
            tmp.push(`${key}=${body[key]}`);
        }
    });
    var signStr = tmp.join('&');

    return utils.sha1(signStr);
}

function getSign(body, secret, ops){
    var ops = _.assign(
        {
            algorithm : 'md5',
            lowerCase : false
        }, ops);

    var keyArr = _.keys(body).sort();
    var tmp = [];
    _.each(keyArr, function(key){
        if(body[key] !== undefined){
            tmp.push(`${key}=${body[key]}`);
        }
    });
    tmp.push('key=' + secret);

    var signStr = tmp.join('&');

    var result = utils[ops.algorithm](signStr);
    if(ops.lowerCase){
        return result.toLowerCase();
    }else{
        return result.toUpperCase();
    }
}

/**
 * 显示绑定成功页面
 */
router.get('/wechat/bind/success', function (req, res) {
    res.render('wechat/bind_success');
});
router.get('/wechat/charge/success', function (req, res) {
    res.render('wechat/charge_success', {target : req.query.target});
});

var discount = {
    '中国移动' : 7,
    '中国联通' : 10,
    '中国电信' : 9
};

/**
 * 获取一个号码可充值的流量包
 */
router.get('/wechat/api/mobile/package', function(req, res){
    function * handler (){
        var
            response, body, localeInfo,
            mobile = req.query.mobile,

            queryUrl = 'https://tcc.taobao.com/cc/json/mobile_tel_segment.htm',
            queryParam = {tel : mobile},
            url = commonUtils.buildUrl(queryUrl, queryParam);

        response = yield coRequest.get({url : url, encoding : null});

        if(response.statusCode !== 200){
            throw `request : ${url} \n status : ${response.statusCode}`;
        }

        body = eval(iconv.decode(response.body, 'GBK'));
        localeInfo = {
            province : body.province,
            sp : body.catName,
            subSp : body.carrier
        };

        var spTypeMap = {
            '中国移动' : 1,
            '中国联通' : 2,
            '中国电信' : 3
        };

        var reqBody = {
            account : flowServerAccount,
            type : spTypeMap[localeInfo.sp]
        };

        reqBody.sign = getSign(reqBody, flowServerApiKey, {lowerCase : true});
        reqBody.action = 'getPackage';
        reqBody.v = '1.1';

        url = commonUtils.buildUrl(flowServerUrl, reqBody);
        var result = yield coRequest.get(url);
        if(result.statusCode !== 200){
            throw `request : ${url} \n status : ${response.statusCode}`;
        }

        return _.assign(localeInfo, {packages : JSON.parse(result.body).Packages}, {discount : discount[localeInfo.sp]});
    }

    commonUtils.coHandler(handler, res);
});

/**
 * 手机流量支付接口
 */
router.post('/wechat/api/mobile/flow/charge', function(req, res){
    var user = req.session.user;
    var package = req.body.package;
    var packageName = req.body.packageName;
    var mobile = req.body.mobile;
    var price = Math.round(+req.body.price * 100);
    var clientIP = req.ip.split(':')[3];
    console.log(`通用流量 -- 充值客户端IP:${clientIP}, 充值流量:${package}M`);

    function * handler (){

        var order = {
            order_id : idGen.orderId(user.open_id),
            mobile : mobile,
            amount : price,
            package : packageName,
            payer_id : user._id,
            status : constant.OrderStatus.PAY_NO,
            type : constant.OrderType.MOBILE,
            create_time : new Date()
        };

        var orderInstance = new dao.Order(order);
        var saveResult = yield orderInstance.save();

        var prepayId = yield * wechatUnifiedOrder({
            desc : `通用手机流量${packageName}套餐`,
            orderId : order.order_id,
            price : price,
            ip : clientIP,
            openId : user.open_id,
            callbackUrl : 'http://service.lvyou189.cn/charge/callback'
        });

        var paySignBody = {
            appId : appId,
            timeStamp : (new Date().getTime() / 1000).toFixed(0),
            nonceStr : idGen.nonceStr(),
            'package' : `prepay_id=${prepayId}`,
            signType : 'MD5'
        };

        var paySign = getSign(paySignBody, paykey);

        var finalResult = {
            appId : appId,
            nonceStr : paySignBody.nonceStr,
            timestamp: paySignBody.timeStamp,
            prepayId : prepayId,
            'package' : paySignBody.package,
            signType : paySignBody.signType,
            paySign : paySign
        };

        return finalResult;
    }

    commonUtils.coHandler(handler, res);
});

router.get('/api/discount', function(req, res){
    function * h(){
        return discount;
    }
    commonUtils.coHandler(h, res);
});

router.post('/api/discount', function(req, res){
    function * h(){
        var newDiscount = req.body;
        for(var key in newDiscount){
            if(discount[key] == undefined){
                throw '未知运营商:' + key;
            }
            var d = +newDiscount[key];
            if(d < 0 || d > 10){
                throw `折扣数值应为 0~10 之间的数: ${key}=${d}`;
            }
        }
        discount = newDiscount;
        return 'ok';
    }
    commonUtils.coHandler(h, res);
});

/**
 * 微信验证接口
 */
router.get('/api/dispatch', function (req, res, next) {
    var token = 'leondc';
    var signature = req.query.signature;
    var timestamp = req.query.timestamp;
    var echostr = req.query.echostr;
    var nonce = req.query.nonce;

    var oriArray = [token, nonce, timestamp];
    oriArray = oriArray.sort();

    var original = oriArray.join('');

    var shaObj = new jsSHA('SHA-1', "TEXT");
    shaObj.update(original);
    var scyptoString = shaObj.getHash("HEX");

    if (scyptoString === signature) {
        res.send(echostr);
    } else {
        res.json('error');
    }
});

/**
 * 微信推送消息和时间处理接口
 */
router.post('/api/dispatch', function (req, res, next) {
    var post_data = "";
    req.on("data", function (data) {
        post_data = data;
    });
    req.on("end", function () {
        var xmlStr = post_data.toString('utf-8', 0, post_data.length);
        console.log('debug : xmlStr = ' + xmlStr);
        co(function*(){
            var result = yield co_xml2json(xmlStr, {explicitArray: false});
            console.log(result);
            switch (result.xml.MsgType) {
                case constant.MsgType.EVENT:
                {
                    eventHandler(req, res, result, next);
                    break;
                }
                case constant.MsgType.TEXT:
                {
                    textHandler(req, res, result, next);
                    break;
                }
                default :
                {
                    defaultHandler(res, next);
                }
            }
        }).catch(function(err){
            console.log(err);
        });
    });
});

/**
 * 微信推送的事件处理函数
 * @param req
 * @param res
 * @param data
 * @param next
 */
function eventHandler(req, res, data, next) {
    var
        open_id = data.xml.FromUserName,
        resp = {
            ToUserName: data.xml.FromUserName,
            FromUserName: data.xml.ToUserName,
            CreateTime: new Date().getTime(),
            MsgType: constant.MsgType.TEXT
        };

    switch (data.xml.Event) {
        case constant.eventType.subscribe :
        {
            dao.User.find({open_id : open_id}, function(err, docs){
                if(docs && docs.length > 0){
                    resp.Content = '欢迎您再次关注旅游WIFI公众平台，您可以点击「绑定卡号」完成流量卡绑定操作后，点击「查询实时流量」按钮，查看流量卡实时流量。';
                    var xmlResp = xmlBuilder.buildObject(resp);
                    res.send(xmlResp);

                    dao.User.update({open_id : open_id}, {status : 0});
                }else{
                    resp.Content = '欢迎关注旅游WIFI公众平台，您可以点击「绑定卡号」完成流量卡绑定操作后，点击「查询实时流量」按钮，查看流量卡实时流量。';
                    var xmlResp = xmlBuilder.buildObject(resp);
                    res.send(xmlResp);

                    var user = {
                        open_id: data.xml.FromUserName,
                        status: 0
                    };
                    new dao.User(user).save(function (err, product, numberAffected) {
                        if (!err) {
                            console.log(`db save succ, add :${product}`);
                        } else {
                            console.log(`db save fail, err : ${err}`);
                        }
                    });
                }
            });
            break;
        }
        case constant.eventType.unsubscribe :
        {
            res.end();
            var condition = {open_id: data.xml.FromUserName};
            var update = {status: 1};
            dao.User.update(condition, update, function (err) {
                if (err) {
                    console.log(`db update fail, err : ${err}`);
                } else {
                    console.log(`db update succ, User : ${data.xml.FromUserName}`);
                }
            });
            break;
        }
        case constant.eventType.view:
        {
            console.log(data.xml.EventKey);
            res.end();
            break;
        }
        case constant.eventType.click:
        {
            if (data.xml.EventKey === 'V2000_QUARY_FLOW') {

                dao.User.find({open_id : open_id}, function(e, docs){
                    if(e || docs.length == 0 || !docs[0].card_id){
                        resp.Content = '请先完成绑定卡号的操作,再查询流量,谢谢';
                        var xmlResp = xmlBuilder.buildObject(resp);
                        res.send(xmlResp);
                    }else{
                        //如果绑定过卡号
                        var user = docs[0];
                        co(function*() {
                            var card = yield dao.Card.findOne({card_id : user.card_id});
                            if(!card){
                                resp.Content = '绑定的卡号已注销,无法查询';
                                var xmlResp = xmlBuilder.buildObject(resp);
                                return res.send(xmlResp);
                            }

                            var month = moment().format('YYYYMM');
                            var url = `http://127.0.0.1:9001/flowset?mobile=${card.mobile}&month=${month}`;
                            console.log('已绑定卡号------------------------------------');
                            console.log(`user = ${user}`);
                            console.log(url);
                            var response = yield coRequest(url);
                            if (response.statusCode == 200) {
                                var body = JSON.parse(response.body);
                                resp.Content = commonUtils.flowsetProfile(body);
                                console.log(resp);
                                var xmlResp = xmlBuilder.buildObject(resp);
                                res.send(xmlResp);
                            } else {
                                res.Content = '查询出错了';
                                console.log(resp);
                                var xmlResp = xmlBuilder.buildObject(resp);
                                res.send(xmlResp);
                            }
                        }).catch(function (err) {
                            res.Content = '查询出错了';
                            console.log(resp);
                            var xmlResp = xmlBuilder.buildObject(resp);
                            res.send(xmlResp);
                        });
                    }
                });
            }
            else if(data.xml.EventKey === 'V3000_CHARGE_FLOW'){
                co(function*(){
                    var user = yield dao.User.findOne({open_id : open_id});
                    if(!user || !user.card_id){
                        resp.Content = '请先完成绑定卡号的操作,再充值流量,谢谢';
                        var xmlResp = xmlBuilder.buildObject(resp);
                        return res.send(xmlResp);
                    }

                    var card = yield dao.Card.findOne({card_id : user.card_id});
                    if(!card){
                        resp.Content = '绑定的卡号已注销,无法充值';
                        var xmlResp = xmlBuilder.buildObject(resp);
                        return res.send(xmlResp);
                    }

                    resp.Content = `您当前绑定的流量卡:\n${card.card_id}\n请点击<a href="http://service.lvyou189.cn/wechat/auth?view=charge">[充值连接]</a>为该卡充值`;
                    var xmlResp = xmlBuilder.buildObject(resp);
                    return res.send(xmlResp);

                }).catch(function(err){
                    res.Content = '系统异常:' + err;
                    console.log(resp);
                    var xmlResp = xmlBuilder.buildObject(resp);
                    return res.send(xmlResp);
                });
            }
            break;
        }
        default :
        {
            defaultHandler(res, next);
        }

    }
}

function textHandler(req, res, data, next) {
    var resp = {
        ToUserName: data.xml.FromUserName,
        FromUserName: data.xml.ToUserName,
        CreateTime: new Date().getTime(),
        MsgType: constant.MsgType.TEXT,
        Content: '您可以点击「绑定卡号」完成流量卡绑定操作后，点击「查询实时流量」按钮，查看流量卡实时流量。'
    };
    var xmlResp = xmlBuilder.buildObject(resp);
    res.send(xmlResp);
}

function defaultHandler(res, next) {
    res.status(200).end();
}

function chargeReportHandler(order){
    co(function * (){
        var user = yield dao.User.findOne({_id : order.payer_id});
        if(!user){
            return;
        }
        if(order.outer_task_report.Status == 4){
            yield * pushMessageToUser({
                touser : user.open_id,
                template_id : 'vEiYHqFgPQESi6biu6SvwH5e3xc2qBbNLI6Z34QOrBg',
                // url : 'http://weixin.qq.com/download',
                data :{
                    first : {
                        value : '亲,您的流量已充值成功\n'
                    },
                    keyword1 : {
                        value : order.mobile,
                        color : '#173177'
                    },
                    keyword2 : {
                        value : order.package,
                        color : '#173177'
                    },
                    keyword3 : {
                        value : moment(order.update_time).format('YYYY-MM-DD hh:mm:ss')
                    },
                    remark : {
                        value : '\n感谢您的使用'
                    }
                }
            });
        }else if(order.outer_task_report.Status == 5){
            yield * wechatRefund(order);
            yield * pushMessageToUser({
                touser : user.open_id,
                template_id : 'XasxKB0nzGXAwOj1G2CNToEsuuCfQOKOOJx1N5kYlp8',
                // url : 'http://weixin.qq.com/download',
                data :{
                    first : {
                        value : '您好，非常抱歉，您购买的流量因运营商系统原因充值失败，现将为您退款至原支付账户，退款将在1-3个工作日到帐。\n'
                    },
                    keyword1 : {
                        value : order.order_id,
                        color : '#173177'
                    },
                    keyword2 : {
                        value : order.package,
                        color : '#173177'
                    },
                    keyword3 : {
                        value : `${(order.amount / 100).toFixed(2)}元`,
                        color : '#173177'
                    },
                    keyword4 : {
                        value : order.mobile,
                        color : '#173177'
                    },
                    remark : {
                        value : '\n如有疑问，请联系公众号客服\n感谢您的使用, 欢迎再次购买. '
                    }
                }
            });
        }
    }).catch(function(err){
        console.log(err);
    });
}

function * pushMessageToUser(opt){
    if(!opt){
        return;
    }

    var token = yield LicenseCenter.access_token();
    var url = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${token}`;

    var response = yield coRequest.post({
        url : url,
        json : true,
        body : opt
    });
    console.log(response.body);
}

function * wechatUnifiedOrder(ops){

    var postData = {
        appid : appId,
        mch_id : mchId,
        device_info : 'WEB',
        nonce_str : idGen.nonceStr(),
        body : ops.desc,
        out_trade_no : ops.orderId,          //'内部订单号',
        total_fee : ops.price,
        spbill_create_ip : ops.ip,
        notify_url : ops.callbackUrl,
        trade_type : 'JSAPI',
        openid : ops.openId
    };
    postData.sign = getSign(postData, paykey);
    var postXML = xmlBuilder.buildObject(postData);

    console.log('prepay request 2 wechat ------->');
    var response = yield coRequest.post({
        url : 'https://api.mch.weixin.qq.com/pay/unifiedorder',
        body : postXML
    });
    console.log('prepay req fin');
    //request error
    if (response.statusCode !== 200) {
        throw '微信支付(统一订单)服务错误';
    }

    var result = yield co_xml2json(response.body, {explicitArray: false});
    //签名错误等数据错误
    if(result.xml.return_code === 'FAIL') {
        throw result.xml.return_msg;
    }
    //业务错误
    if(result.xml.result_code === 'FAIL'){
        throw result.xml.err_code_des;
    }

    return result.xml.prepay_id;
}

function * wechatRefund(order){
    var url = 'https://api.mch.weixin.qq.com/secapi/pay/refund';
    var postData = {
        appid : appId,
        mch_id  : mchId,
        nonce_str : idGen.nonceStr(),
        out_trade_no : order.order_id,
        out_refund_no : order.order_id,
        total_fee : order.amount,
        refund_fee : order.amount,
        op_user_id : mchId
    };
    postData.sign = getSign(postData, paykey);
    var postXML = xmlBuilder.buildObject(postData);

    console.log('refund request 2 wechat ------->' + postXML);
    var response = yield coRequest.post({
        url : url,
        body : postXML,
        cert: fs.readFileSync(certFile),
        key: fs.readFileSync(keyFile),
        passphrase: mchId,
        ca: fs.readFileSync(caFile)
    });
    console.log('refund req fin');
    //request error
    if (response.statusCode !== 200) {
        throw '微信支付(退款)服务错误';
    }

    var result = yield co_xml2json(response.body, {explicitArray: false});
    //签名错误等数据错误
    if(result.xml.return_code === 'FAIL') {
        throw result.xml.return_msg;
    }
    //业务错误
    if(result.xml.result_code === 'FAIL'){
        throw result.xml.err_code_des;
    }

    return result.xml.result_code;
}

module.exports = router;
